from typing import Dict, Any, List, Optional
import pandas as pd
from dao.backtest_result_dao import BacktestResultDao
from core.database import DatabaseManager
from loguru import logger


class BacktestResultService:
    def __init__(self, db_manager: DatabaseManager = None):
        self.dao = BacktestResultDao(db_manager)

    def save_backtest_result(self, params: Dict[str, Any], statistics: Dict[str, Any], 
                           results_df: pd.DataFrame = None) -> Optional[int]:
        """
        Save a backtest result with parameters and statistics.
        
        :param params: Backtest parameters dictionary
        :param statistics: Backtest statistics dictionary
        :param results_df: DataFrame containing detailed results
        :return: The ID of the saved record, or None if failed
        """
        try:
            result_id = self.dao.save_backtest_result(params, statistics, results_df)
            if result_id:
                logger.info(f"回测结果已保存，ID: {result_id}")
                return result_id
            else:
                logger.error("保存回测结果失败")
                return None
        except Exception as e:
            logger.exception(f"保存回测结果时发生错误: {e}")
            return None

    def get_backtest_result(self, result_id: int) -> Optional[Dict[str, Any]]:
        """
        Retrieve a backtest result by ID.
        
        :param result_id: The ID of the backtest result
        :return: Dictionary containing the backtest result
        """
        try:
            return self.dao.get_backtest_result(result_id)
        except Exception as e:
            logger.exception(f"获取回测结果时发生错误: {e}")
            return None

    def get_all_backtest_results(self, limit: int = 100, offset: int = 0) -> List[Dict[str, Any]]:
        """
        Retrieve all backtest results with pagination.
        
        :param limit: Maximum number of results to return
        :param offset: Number of results to skip
        :return: List of dictionaries containing backtest results
        """
        try:
            return self.dao.get_all_backtest_results(limit, offset)
        except Exception as e:
            logger.exception(f"获取回测结果列表时发生错误: {e}")
            return []

    def get_backtest_results_by_strategy(self, strategy_name: str) -> List[Dict[str, Any]]:
        """
        Retrieve backtest results for a specific strategy.
        
        :param strategy_name: The strategy name to filter by
        :return: List of dictionaries containing backtest results
        """
        try:
            return self.dao.get_backtest_results_by_strategy(strategy_name)
        except Exception as e:
            logger.exception(f"获取策略回测结果时发生错误: {e}")
            return []

    def delete_backtest_result(self, result_id: int) -> bool:
        """
        Delete a backtest result by ID.
        
        :param result_id: The ID of the backtest result to delete
        :return: True if successful, False otherwise
        """
        try:
            success = self.dao.delete_backtest_result(result_id)
            if success:
                logger.info(f"回测结果已删除，ID: {result_id}")
            else:
                logger.warning(f"删除回测结果失败，ID: {result_id}")
            return success
        except Exception as e:
            logger.exception(f"删除回测结果时发生错误: {e}")
            return False

    def get_backtest_summary(self, limit: int = 10) -> List[Dict[str, Any]]:
        """
        Get a summary of recent backtest results for display.
        
        :param limit: Number of recent results to include
        :return: List of summarized backtest results
        """
        try:
            results = self.dao.get_all_backtest_results(limit, 0)
            
            # Add formatted data for display
            for result in results:
                # Format return as percentage
                if result.get('total_return'):
                    result['total_return_pct'] = f"{result['total_return'] * 100:.2f}%"
                if result.get('annual_return'):
                    result['annual_return_pct'] = f"{result['annual_return'] * 100:.2f}%"
                if result.get('max_ddpercent'):
                    result['max_ddpercent_pct'] = f"{result['max_ddpercent'] * 100:.2f}%"
                    
                # Format date
                if result.get('create_time'):
                    try:
                        from datetime import datetime
                        # Assuming create_time is in string format
                        dt = datetime.fromisoformat(result['create_time'].replace('Z', '+00:00'))
                        result['create_time_formatted'] = dt.strftime('%Y-%m-%d %H:%M:%S')
                    except:
                        result['create_time_formatted'] = result['create_time']
                        
            return results
        except Exception as e:
            logger.exception(f"获取回测结果摘要时发生错误: {e}")
            return []

    def compare_backtest_results(self, result_ids: List[int]) -> Optional[Dict[str, Any]]:
        """
        Compare multiple backtest results.
        
        :param result_ids: List of backtest result IDs to compare
        :return: Dictionary containing comparison data
        """
        try:
            if not result_ids:
                return None
                
            results = []
            for result_id in result_ids:
                result = self.dao.get_backtest_result(result_id)
                if result:
                    results.append(result)
                    
            if not results:
                return None
                
            # Create comparison structure
            comparison = {
                'strategies': [r['strategy_name'] for r in results],
                'symbols': [r['vt_symbol'] for r in results],
                'total_returns': [r.get('total_return', 0) for r in results],
                'annual_returns': [r.get('annual_return', 0) for r in results],
                'sharpe_ratios': [r.get('sharpe_ratio', 0) for r in results],
                'max_drawdowns': [r.get('max_ddpercent', 0) for r in results],
                'win_rates': [r.get('win_rate', 0) for r in results],
                'results': results
            }
            
            return comparison
            
        except Exception as e:
            logger.exception(f"比较回测结果时发生错误: {e}")
            return None